"""编码处理模块

负责对视频分析结果进行编码映射、验证和规范化处理
"""

import logging
from typing import Dict, List, Any, Tuple, Optional

from config.encoding_categories import ENCODING_CATEGORIES, NON_ENCODING_FIELDS, OUTPUT_ORDER

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)


class EncodingProcessor:
    """编码处理器类，负责编码映射、验证和规范化处理"""
    
    def process_encoding(self, video_analysis: Dict[str, Any]) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:
        """处理视频分析结果的编码
        
        Args:
            video_analysis: 原始视频分析结果
        
        Returns:
            Tuple[处理后的结果, 验证警告列表]
        """
        logger.info("开始编码处理")
        
        processed_result = {}
        validation_warnings = []
        
        # 处理编码类目
        for category, options in ENCODING_CATEGORIES.items():
            if category in video_analysis:
                original_value = video_analysis[category]
                
                # 编码映射
                mapped_value, warnings = self._map_encoding(category, original_value, options)
                processed_result[category] = mapped_value
                validation_warnings.extend(warnings)
            else:
                # 缺失的编码类目设为默认值并记录警告
                processed_result[category] = '其他'
                validation_warnings.append({
                    'category': category,
                    'level': 'warning',
                    'message': f'缺少编码类目: {category}，已设置为默认值 "其他"'
                })
        
        # 处理非编码字段
        for key, value in video_analysis.items():
            if key not in ENCODING_CATEGORIES and key not in processed_result:
                processed_result[key] = value
        
        # 验证编码的有效性
        validation_warnings.extend(self._validate_encoding(processed_result))
        
        # 确保输出格式符合要求
        formatted_result = self._format_result(processed_result)
        
        logger.info(f"编码处理完成，生成 {len(validation_warnings)} 条验证警告")
        return formatted_result, validation_warnings
    
    def _map_encoding(self, category: str, value: Any, options: Dict[str, Any]) -> Tuple[str, List[Dict[str, Any]]]:
        """将分析结果映射到标准编码
        
        Args:
            category: 编码类目
            value: 原始值
            options: 编码选项配置
        
        Returns:
            Tuple[映射后的编码值, 警告列表]
        """
        warnings = []
        
        # 如果值为None或空字符串，设为默认值
        if value is None or value == '':
            warnings.append({
                'category': category,
                'level': 'warning',
                'message': f'编码值为空，已设置为默认值 "其他"'
            })
            return '其他', warnings
        
        # 转为字符串并清理
        value_str = str(value).strip()
        
        # 检查是否为标准编码选项
        standard_options = options.get('options', [])
        if value_str in standard_options:
            return value_str, warnings
        
        # 使用关键词映射
        keyword_mapping = options.get('keyword_mapping', {})
        mapped_value = self._map_by_keywords(value_str, keyword_mapping)
        
        if mapped_value:
            warnings.append({
                'category': category,
                'level': 'info',
                'message': f'将值 "{value_str}" 映射为标准编码 "{mapped_value}"'
            })
            return mapped_value, warnings
        
        # 都没匹配上，设为默认值
        warnings.append({
            'category': category,
            'level': 'warning',
            'message': f'无法识别的值 "{value_str}"，已设置为默认值 "其他"'
        })
        return '其他', warnings
    
    def _map_by_keywords(self, value: str, keyword_mapping: Dict[str, List[str]]) -> Optional[str]:
        """通过关键词映射值
        
        Args:
            value: 要映射的值
            keyword_mapping: 关键词映射字典
        
        Returns:
            映射后的编码值，如果没有匹配则返回None
        """
        # 转换为小写用于匹配
        value_lower = value.lower()
        
        # 检查是否包含任何关键词
        for target_value, keywords in keyword_mapping.items():
            for keyword in keywords:
                if keyword.lower() in value_lower:
                    return target_value
        
        return None
    
    def _validate_encoding(self, result: Dict[str, Any]) -> List[Dict[str, Any]]:
        """验证编码的有效性
        
        Args:
            result: 处理后的结果
        
        Returns:
            验证警告列表
        """
        warnings = []
        
        for category, options in ENCODING_CATEGORIES.items():
            if category in result:
                value = result[category]
                standard_options = options.get('options', [])
                
                # 检查是否为标准选项之一
                if value not in standard_options:
                    warnings.append({
                        'category': category,
                        'level': 'warning',
                        'message': f'编码值 "{value}" 不在标准选项列表中'
                    })
        
        return warnings
    
    def _format_result(self, result: Dict[str, Any]) -> Dict[str, Any]:
        """格式化结果，确保符合输出规范
        
        Args:
            result: 原始结果
        
        Returns:
            格式化后的结果
        """
        formatted = {}
        
        # 按照预定义的输出顺序组织字段
        for field in OUTPUT_ORDER:
            if field in result:
                formatted[field] = result[field]
            else:
                # 对于编码类目，默认值为'其他'
                if field in ENCODING_CATEGORIES:
                    formatted[field] = '其他'
                else:
                    formatted[field] = ''
        
        # 添加剩余的非编码字段
        for key, value in result.items():
            if key not in ENCODING_CATEGORIES and key not in formatted:
                formatted[key] = value
        
        return formatted
    
    def normalize_text(self, text: Any) -> str:
        """规范化文本内容
        
        Args:
            text: 原始文本
        
        Returns:
            规范化后的文本
        """
        if text is None:
            return ''
        
        # 转为字符串并去除首尾空白
        normalized = str(text).strip()
        
        # 处理特殊字符和空白
        normalized = normalized.replace('\n', ' ').replace('\r', ' ')
        normalized = ' '.join(normalized.split())  # 多个空格替换为单个空格
        
        return normalized
    
    def validate_result_completeness(self, result: Dict[str, Any]) -> List[Dict[str, Any]]:
        """验证结果的完整性
        
        Args:
            result: 处理后的结果
        
        Returns:
            完整性验证警告列表
        """
        warnings = []
        
        # 检查所有编码类目是否都有值
        for category in ENCODING_CATEGORIES:
            if category not in result or result[category] is None or result[category] == '':
                warnings.append({
                    'category': category,
                    'level': 'error',
                    'message': f'编码类目 "{category}" 缺失或为空'
                })
            elif result[category] == '其他':
                warnings.append({
                    'category': category,
                    'level': 'warning',
                    'message': f'编码类目 "{category}" 被设为默认值 "其他"'
                })
        
        # 检查必要的非编码字段
        required_fields = ['视频标题', '视频描述', '视频URL']
        for field in required_fields:
            if field not in result or result[field] is None or result[field] == '':
                warnings.append({
                    'category': field,
                    'level': 'warning',
                    'message': f'必要字段 "{field}" 缺失或为空'
                })
        
        return warnings
    
    def get_encoding_statistics(self, result: Dict[str, Any]) -> Dict[str, Any]:
        """获取编码统计信息
        
        Args:
            result: 处理后的结果
        
        Returns:
            统计信息字典
        """
        stats = {
            'total_encoding_fields': len(ENCODING_CATEGORIES),
            'default_values_count': 0,
            'encoding_distribution': {}
        }
        
        # 统计各编码类目的分布
        for category in ENCODING_CATEGORIES:
            value = result.get(category, '其他')
            
            # 统计默认值数量
            if value == '其他':
                stats['default_values_count'] += 1
            
            # 更新分布统计
            if category not in stats['encoding_distribution']:
                stats['encoding_distribution'][category] = {}
            
            if value not in stats['encoding_distribution'][category]:
                stats['encoding_distribution'][category][value] = 0
            stats['encoding_distribution'][category][value] += 1
        
        # 计算默认值比例
        stats['default_value_ratio'] = stats['default_values_count'] / stats['total_encoding_fields']
        
        return stats